package io.netty.example.mytest.nio.reactor;

import java.io.IOException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @ClassName InitiationDispatcher
 * @Description 事件调度器
 * @Author dukezeng
 * @CreatedTime 2019/4/13 18:05
 * @Version 1.0
 **/
public class InitiationDispatcher {
    private ConcurrentMap<Integer, EventHandler> eventHandlerMap = new ConcurrentHashMap<Integer, EventHandler>();
    /**
     * 同步事件分离器
     */
    private Selector demultiplexer;

    public InitiationDispatcher() {
        try {
            demultiplexer = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void registerHandler(Integer eventType, EventHandler eventHandler) {
        eventHandlerMap.putIfAbsent(eventType, eventHandler);
    }

    public void removeHandler(Integer eventType, EventHandler eventHandler) {
        eventHandlerMap.remove(eventType, eventHandler);
    }

    /**
     * 绑定渠道到多路复用器
     * @param eventType
     * @param selectableChannel
     * @throws Exception
     */
    public void registerChannel(Integer eventType, SelectableChannel selectableChannel) throws Exception {
        selectableChannel.register(demultiplexer, eventType);
    }

    public void handleEvents() {
        try {
            while (true) {
                //等待就绪事件
                demultiplexer.select();

                Set<SelectionKey> readyHandles = demultiplexer.selectedKeys();
                Iterator<SelectionKey> handleIterator = readyHandles.iterator();
                while (handleIterator.hasNext()) {
                    SelectionKey handle = handleIterator.next();

                    if (handle.isAcceptable()) {
                        EventHandler acceptHandler = eventHandlerMap.get(SelectionKey.OP_ACCEPT);
                        acceptHandler.handleEvent(handle);
                    }

                    if (handle.isReadable()) {
                        EventHandler readHandler = eventHandlerMap.get(SelectionKey.OP_READ);
                        readHandler.handleEvent(handle);
                        handleIterator.remove();
                    }

                    if (handle.isWritable()) {
                        EventHandler writeHandler = eventHandlerMap.get(SelectionKey.OP_WRITE);
                        writeHandler.handleEvent(handle);
                        handleIterator.remove();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    //=====================================================================
    public Selector getDemultiplexer() {
        return demultiplexer;
    }

    public void setDemultiplexer(Selector demultiplexer) {
        this.demultiplexer = demultiplexer;
    }
}
